package cn.cloudreal.cbms.castDetail.service.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.cloudreal.cbms.castDetail.dao.ChargeDao;
import cn.cloudreal.cbms.castDetail.service.ChargeService;
import cn.cloudreal.cbms.common.util.Arith;
import cn.cloudreal.cbms.common.util.DatadicContext;
import cn.cloudreal.cbms.common.util.StringUtils;
import cn.cloudreal.cbms.vo.Charge;
import cn.cloudreal.cbms.vo.Dictionary;
import cn.cloudreal.cbms.vo.FundBudget;
import cn.cloudreal.cbms.vo.LevelRule;
import cn.cloudreal.cbms.vo.MediaPrice;
import cn.cloudreal.cbms.vo.ProjectMedium;
import cn.cloudreal.cbms.vo.SourcePlanYear;

public class ChargeServcieImpl implements ChargeService
{
    ChargeDao chargeDao = null;
    
    /**
     * 根据媒体价格id取得预算折扣阶梯
     * @param priceId
     * @return
     */
    public LevelRule getUnPromotionUsedRatio(Map condition)
    {
        return chargeDao.getUnPromotionUsedRatio(condition);
    }

    /**
     * 根据年度地市和费用类型、费用子类取得预算值
     * @param condition
     * @return
     */
    public FundBudget getMediaSummarieByYd(Map condition)
    {
        return chargeDao.getMediaSummarieByYd(condition);
    }
    
    public ChargeDao getChargeDao()
    {
        return chargeDao;
    }

    public void setChargeDao(ChargeDao chargeDao)
    {
        this.chargeDao = chargeDao;
    }

    public List<Dictionary> getCostTypeByProMedID(Map condition)
    {
        return chargeDao.getCostTypeByProMedID(condition);
    }

    public List<Dictionary> getSubCostTypeByProMedIDCostType(Map condition)
    {
        return chargeDao.getSubCostTypeByProMedIDCostType(condition);
    }

    /**
     * 保存项目费用信息
     * 
     */
    synchronized public void saveProjectMedioPrice(List<Charge> charges)
    {
        if(charges != null && !charges.isEmpty())
        {
            boolean isDel = false;
            
            for(Charge charge : charges)
            {
                if(charge == null)
                {
                    continue;
                }
                
                // 删除费用信息
                if(!isDel)
                {
                    delPrice(charge.getProMedID());
                    isDel = true;
                }
                
                // 资金类型为预算的时候
                if("1".equals(charge.getFundType()) || "2".equals(charge.getFundType()))
                {
                    // 计算随单配赠资源
                    Double promotionBCount = getPromotionBCount(charge);
                    if(promotionBCount != null)
                    {
                        // 减去随单赠送资源
                        charge.setFundAmount(Arith.sub(charge.getFundAmount(), promotionBCount));
                    }
                }
                
                // 更新媒体价格表的费用总量
                if("1".equals(charge.getIsJl()))
                {
                    updateMedioTotalPay(charge);
                }
                
                // 更新预算剩余额
                updatePlanAmount(charge);
                
                charge.setTsbjType(StringUtils.isEmpty(charge.getTsbjType()) ? "" : charge.getTsbjType());
                
                // 保存项目价格信息
                chargeDao.saveProjectMedioPrice(getJljfType(charge));
            }
        }
    }
    
    /**
     * 计算并保存定向折扣资源
     * @param charge
     * @return
     */
    private Double getMediumOrientDiscount(Charge charge)
    {
        // 取得定向折扣
        ProjectMedium projectMedium = chargeDao.getProjectMediumByProMedID(charge.getProMedID());
        double mediumOrientDiscount = projectMedium.getMediumOrientDiscount();
        Charge mediumOrientCharge = new Charge();
        
        // 项目媒介编号
        mediumOrientCharge.setProMedID(charge.getProMedID());
        // 资金类型
        mediumOrientCharge.setFundType("8");
        // 计量计返类型
        mediumOrientCharge.setJljfType("1");
        //特殊报价数量
        mediumOrientCharge.setUsedRatio(mediumOrientDiscount);
        // 特殊报价类型
        //mediumOrientCharge.setTsbjType("2");
        mediumOrientCharge.setTsbjType("");
        mediumOrientCharge.setCostType("");
        mediumOrientCharge.setCostSubtype("");
        // 定向折扣
        mediumOrientCharge.setFundAmount(charge.getFundAmount() * (100 - mediumOrientDiscount) / 100);
        
        if(mediumOrientCharge.getFundAmount() != 0)
        {
            // 保存随单赠送信息
            chargeDao.saveProjectMedioPrice(mediumOrientCharge);
        }
        
        return mediumOrientCharge.getFundAmount();
    }
    
    /**
     * 计算并保存随单赠送资源
     * @param charge
     * @return
     */
    private Double getPromotionBCount(Charge charge)
    {
        // 取得媒体随单配赠信息
        Map usedRatioCondition = new HashMap();
        usedRatioCondition.put("proMedID", charge.getProMedID());
        usedRatioCondition.put("saleType", "2");
        LevelRule levelRule = chargeDao.getUnPromotionUsedRatio(usedRatioCondition);
        
        // 如果随单配赠存在
        if(levelRule != null)
        {
            Charge promotionBCharge = new Charge();
            // 项目媒介编号
            promotionBCharge.setProMedID(charge.getProMedID());
            // 资金类型
            promotionBCharge.setFundType("6");
            // 计量计返类型
            promotionBCharge.setJljfType("1");
            //特殊报价数量
            //promotionBCharge.setTsbjAmount(levelRule.getLevelDiscount());
            
            // 折扣
            if("1".equals(levelRule.getLevelPromotionType()))
            {
                // 特殊报价类型
                promotionBCharge.setUsedRatio(levelRule.getLevelDiscount());
                
                // 随单赠送数量
                promotionBCharge.setFundAmount(Arith.mul(charge.getFundAmount(), Arith.div(Arith.sub(100, levelRule.getLevelDiscount()), 100)));
            }else if("2".equals(levelRule.getLevelPromotionType()))
            {
                // 特殊报价类型
                //promotionBCharge.setTsbjType("1");
                
                // 随单赠送数量
                promotionBCharge.setFundAmount(levelRule.getLevelDiscount());
            }
            
            promotionBCharge.setCostType("");
            promotionBCharge.setCostSubtype("");
            promotionBCharge.setTsbjType("");
            
            //promotionBCharge.setBcdkkanli(promotionBCharge.getFundAmount());
            
            // 保存随单赠送信息
            if(promotionBCharge.getFundAmount() != 0)
            {
                chargeDao.saveProjectMedioPrice(promotionBCharge);
            }
            
            return promotionBCharge.getFundAmount();
        }
        
        return null;
    }
    
    /**
     * 更新媒体发生总金额
     * @param charge
     */
    private void updateMedioTotalPay(Charge charge)
    {
        Map param = new HashMap();
        param.put("fundAmount", charge.getFundAmount());
        param.put("proMedID", charge.getProMedID());
        chargeDao.updateMedioTotalPay(param);
    }

    /**
     * 更新媒体预算
     * @param charge
     */
    private void updatePlanAmount(Charge charge)
    {
        Dictionary dic = DatadicContext.getInstance().getDatadicObject(charge.getCostSubtype(), "FYLX");
        
        Map param = new HashMap();
        // id
        param.put("id", charge.getId());
        
        // 媒体费用 
        if("2".equals(dic.getExtAttr1()))
        {
            // 常规价格常规折扣投放  常规价格特殊折扣存放 
            if("1".equals(charge.getFundType()) || "2".equals(charge.getFundType()))
            {
                param.put("unPromotionAmountUsed", charge.getFundAmount());
            }
            
            // 年度返还资源投放
            if("4".equals(charge.getFundType()))
            {
                param.put("returnSourceAmountUsed", charge.getFundAmount());
            }
            // 常规配赠资源投放
            if("5".equals(charge.getFundType()))
            {
                param.put("promotionAmountUsed", charge.getFundAmount());
            }
            // 增量资源投放
            if("9".equals(charge.getFundType()))
            {
                param.put("IncrePromotionAmountUsed", charge.getFundAmount());
            }
            
            chargeDao.updateMedioAmountUsed(param);
        }
        // 公共费用
        else
        {
            param.put("usedBudget", charge.getFundAmount());
            chargeDao.updateGGAmountUsed(param);
        }
    }
    
    /**
     * 得到计量计返类型
     * @return
     */
    private Charge getJljfType(Charge charge)
    {
        // 计量计返
        if("1".equals(charge.getIsJf()) && "1".equals(charge.getIsJl()))
        {
            charge.setJljfType("4");
        }
        // 计返不计量
        if("1".equals(charge.getIsJf()) && "0".equals(charge.getIsJl()))
        {
            charge.setJljfType("2");
        }
        // 计量不计返
        if("0".equals(charge.getIsJf()) && "1".equals(charge.getIsJl()))
        {
            charge.setJljfType("3");
        }
        // 不计量不计返
        if("0".equals(charge.getIsJf()) && "0".equals(charge.getIsJl()))
        {
            charge.setJljfType("1");
        }
        
        return charge;
    }
    
    public SourcePlanYear getMediaSummariePcc(Map condition)
    {
        return chargeDao.getMediaSummariePcc(condition);
    }

    public ProjectMedium getProjectMediumByProMedID(int proMedID)
    {
        // TODO Auto-generated method stub
        return chargeDao.getProjectMediumByProMedID(proMedID);
    }

    /**
     * 根据项目媒介id取得项目费用信息
     * @param condition
     * @return
     */
    public List<Charge> getChargesByProMedID(Integer proMedID)
    {
        return chargeDao.getChargesByProMedID(proMedID);
    }

    /**
     * 删除项目媒介费用
     * @param condition
     * @return
     */
    synchronized public void delProjectMedioPrice(Integer proMedID)
    {
        delPrice(proMedID);
    }
    
    private void delPrice(Integer proMedID)
    {
        // 取得项目媒介价格信息
        List<Charge> charges = chargeDao.getChargesByProMedID(proMedID);
        if(charges == null || charges.isEmpty())
        {
            return;
        }
        
        //遍历费用信息
        for(Charge charge : charges)
        {
            Map param = new HashMap();
            param.put("proMedID", proMedID);
            param.put("id", charge.getId());
            
            // 预算类型
            String costType = charge.getCostType();
            
            // 预算子类
            String costSubType = charge.getCostSubtype();
            
            // 判断是否计量
            if("3".equals(charge.getJljfType()) || "4".equals(charge.getJljfType()))
            {
                param.put("fundAmount", charge.getFundAmount());
                
                // 更新媒体发生总金额
                chargeDao.updateMedioTotalPayByProMedID(param);
            }
            
            // 判断费用是否出自预算
            if(StringUtils.isEmpty(costSubType))
            {
                continue;
            }
            
            param.put("costType", costType);
            param.put("costSubType", costSubType);
            
            Dictionary dic = DatadicContext.getInstance().getDatadicObject(charge.getCostSubtype(), "FYLX");
            
            // 媒体预算
            if("2".equals(dic.getExtAttr1()))
            {
                // 常规价格常规折扣投放  常规价格特殊折扣存放 
                if("1".equals(charge.getFundType()) || "2".equals(charge.getFundType()))
                {
                    param.put("unPromotionAmountUsed", charge.getFundAmount());
                }
                
                // 年度返还资源投放
                if("4".equals(charge.getFundType()))
                {
                    param.put("returnSourceAmountUsed", charge.getFundAmount());
                }
                // 常规配赠资源投放
                if("5".equals(charge.getFundType()))
                {
                    param.put("promotionAmountUsed", charge.getFundAmount());
                }
                // 增量资源投放
                if("9".equals(charge.getFundType()))
                {
                    param.put("IncrePromotionAmountUsed", charge.getFundAmount());
                }
                
                chargeDao.updateMedioAmountUsedByProMedID(param);
            }
            // 公共预算
            else
            {
                param.put("usedBudget", charge.getFundAmount());
                chargeDao.updateGGAmountUsedByProMedID(param);
            }
        }
        
        // 删除项目费用信息
        chargeDao.delChargesbyProMedID(proMedID);
    }

    /**
     * 根据项目媒介id取得项目价格信息
     * @param condition
     * @return
     */
    public MediaPrice getMediaPriceByProMedID(Integer proMedID)
    {
        return chargeDao.getMediaPriceByProMedID(proMedID);
    }
}
